﻿using System;
using System.Collections.Generic;
using fastCSharp;
using fastCSharp.threading;
using fastCSharp.code.cSharp;
using System.Threading;

namespace diantou.web
{
    /// <summary>
    /// 长连接轮询
    /// </summary>
    /// <typeparam name="pollType"></typeparam>
    abstract class poll<pollType> : webView.view<pollType>
        where pollType : poll<pollType>
    {
        /// <summary>
        /// 是否空轮询
        /// </summary>
        protected bool ifNoneMatch;
        /// <summary>
        /// 是否通过验证
        /// </summary>
        [fastCSharp.emit.webView.clearMember]
        protected bool isVerify;
    }
    /// <summary>
    /// 长连接轮询
    /// </summary>
    [fastCSharp.code.cSharp.ajax(IsAttribute = true)]
    [fastCSharp.code.cSharp.webView(IsAjax = true, IsPool = true, IsPage = false)]
    partial class poll : poll<poll>
    {
        /// <summary>
        /// 连接数量
        /// </summary>
        internal static int AsynchronousCount;
        /// <summary>
        /// 空轮询标识
        /// </summary>
        internal static readonly byte[] NullETag = new byte[] { (byte)'n' };
        /// <summary>
        /// 长连接轮询
        /// </summary>
        internal static fastCSharp.web.poll Poll = new fastCSharp.web.poll();
        /// <summary>
        /// 每秒请求数量
        /// </summary>
        internal static secondCount SecondCount = new secondCount(fastCSharp.config.http.Default.CountSeconds);
        /// <summary>
        /// 获取轮询验证信息
        /// </summary>
        /// <param name="isVerify"></param>
        /// <returns></returns>
        [fastCSharp.code.cSharp.ajax]
        public fastCSharp.web.poll.verifyInfo Verify(out bool isVerify)
        {
            diantou.dataAccess.user user = pub.GetCurrentUser(this);
            if (user != null)
            {
                isVerify = true;
                return poll.Poll.Get(user.Id);
            }
            isVerify = false;
            return default(fastCSharp.web.poll.verifyInfo);
        }
        /// <summary>
        /// 是否新发布服务(没有加载页面缓存)
        /// </summary>
        private static int isNewServer;
        ///// <summary>
        ///// 用户标识
        ///// </summary>
        //private int userId;
        /// <summary>
        /// 轮询信息
        /// </summary>
        private sealed class pollInfo
        {
            /// <summary>
            /// 头部信息
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public diantou.dataAccess.poll.headerBase Header;
            /// <summary>
            /// 通知项
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public notice.item[] Notices;
            /// <summary>
            /// 关注的最新动态
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public userItem[] Focus;
            /// <summary>
            /// 测试集合
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public diantou.dataAccess.judgeItem.userJudgeItem[] JudgeItem;
            /// <summary>
            /// 提交
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public diantou.dataModel.judgeState Judge;
            /// <summary>
            /// 比赛动态
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public diantou.dataAccess.contestJudge.finishedJudge[] ContestJudges;
            /// <summary>
            /// 关注的收藏动态
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public int Favorite;
            ///// <summary>
            ///// 今日问题数量
            ///// </summary>
            //public int Today;
            /// <summary>
            /// 最后查询的日志标识
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax]
            public int LogId;
            /// <summary>
            /// 测试信息更新版本
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public int JudgeVersion;
            /// <summary>
            /// 是否绑定微信
            /// </summary>
            [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
            public bool IsWeixin;
        }
        /// <summary>
        /// 是否新发布服务(没有加载页面缓存)
        /// </summary>
        private struct newServer
        {
            /// <summary>
            /// 是否新发布服务(没有加载页面缓存)
            /// </summary>
            public struct newServerValue
            {
                /// <summary>
                /// 是否新发布服务(没有加载页面缓存)
                /// </summary>
                public byte IsNewServer;
            }
            /// <summary>
            /// 是否验证通过
            /// </summary>
            public byte isVerify;
            /// <summary>
            /// 是否新发布服务(没有加载页面缓存)
            /// </summary>
            public newServerValue value;
        }
        /// <summary>
        /// 长连接轮询信息
        /// </summary>
        [fastCSharp.emit.webView.clearMember]
        [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreNull = true)]
        private pollInfo value;
        /// <summary>
        /// 轮询回调处理
        /// </summary>
        private Action<fastCSharp.net.returnValue<diantou.dataAccess.poll>> onMessageHandle;
        /// <summary>
        /// 当前用户
        /// </summary>
        [fastCSharp.code.cSharp.webView.outputAjax(IsIgnoreCurrent = true)]
        private diantou.dataAccess.user currentUser;
        /// <summary>
        /// 轮询回调处理
        /// </summary>
        /// <param name="value"></param>
        private void onMessage(fastCSharp.net.returnValue<diantou.dataAccess.poll> value)
        {
            Interlocked.Decrement(ref AsynchronousCount);
            if (value.Type == fastCSharp.net.returnValue.type.Success && value.Value != null)
            {
                try
                {
                    diantou.dataAccess.poll poll = value.Value;
                    diantou.dataAccess.poll.header header = poll.Header;
                    subArray<diantou.dataAccess.notice> notices = header.Notices.getFind(notite => notite != null);
                    this.value = new pollInfo
                    {
                        Header = header.IsValue == 0 ? null : header,
                        Notices = notices.Count == 0 ? null : notices.GetArray(item => new notice.item { Notice = item }),
                        Favorite = poll.Favorite,
                        Focus = poll.Focus.getArray(item => new userItem { Item = item, User = poll.User }),
                        Judge = poll.Judge,
                        JudgeItem = poll.JudgeItem,
                        LogId = poll.LogId,
                        ContestJudges = poll.ContestJudges,
                        JudgeVersion = poll.JudgeVersion,
                        IsWeixin = poll.IsWeixin
                    };
                }
                finally { callback(); }
            }
            else if (ifNoneMatch) notChanged304();
            else
            {
                fastCSharp.net.tcp.http.response response = cancelAsynchronous();
                response.SetETag(NullETag);
                callback(ref response);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="verify"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        private bool loadView(fastCSharp.web.poll.verifyInfo verify, diantou.dataAccess.poll.query query)
        {
            SecondCount.Add();
            if (Poll.Verify(ref verify))
            {
                if (verify.UserId == 2 && Interlocked.CompareExchange(ref isNewServer, 1, 0) == 0)
                {
                    AjaxResponse(new newServer { isVerify = 1, value = new newServer.newServerValue { IsNewServer = 1 } });
                    return false;
                }
                if (onMessageHandle == null) onMessageHandle = onMessage;
                ifNoneMatch = requestHeader.IfNoneMatch.Count != 0;
                isVerify = true;
                setAsynchronous();
                Interlocked.Increment(ref AsynchronousCount);
                diantou.dataAccess.tcpCall.poll.get(verify.UserId, query, onMessageHandle);
            }
            return true;
        }
    }
}
